﻿using System;

namespace 装饰模式
{
    class Program
    {
        static void Main(string[] args)
        {
            //Person person = new Person("大海");
            //Console.WriteLine("今天穿啥");
            //BigLammy bigLammy = new BigLammy();//大棉袄
            //Tshirts tshirts = new Tshirts();//T恤
            //WarmPants warm = new WarmPants();//保暖裤

            ////装饰过程
            //bigLammy.Decorate(person);
            //tshirts.Decorate(bigLammy);
            //warm.Decorate(tshirts);
            //warm.show();
            Person person = new Person("大海");
            
            P p = new P();
            S s = new S();
            J j = new J();
            Q q = new Q();
            F f = new F();
            X x = new X();

            p.Test(person);
            s.Test(p);
            j.Test(s);
            q.Test(j);
            f.Test(q);
            x.Test(f);
            x.show();

            ///随意组合
            ///
            Person person1 = new Person("二孩");
            P p1 = new P();
            S s1= new S();
            J j1 = new J();
            Q q1 = new Q();
            F f1 = new F();
            X x1 = new X();
            s1.Test(person1);
            x1.Test(s);
            j1.Test(x);
            p1.Test(j);
            f1.Test(p1);
            f1.show();


            



            /*装饰模式：
             * 为已有功能动态地添加更多的功能地一种方式。
             * 在系统需要新功能是，要向旧的主类中添加新的代码，这些新加的代码通常是装饰了
             * 原有类的核心职责或者主要行为。
             * 而使用装饰模式就类似于把新的功能以挂载的方式附加到就的主类中
             * 从而降低了代码的复杂度
             * 
             * note : 
             * 当新加的东西仅仅是为了满足一些只有在特定情况下才会执行的特殊要求，
             * 哪么使用装饰模式就是一个非常好的解决方案，他把每个要装饰的功能放在单独的类中，
             * 并让这个类包装他所要装饰的对象，因此，当需要执行特殊行为时，客户代码就可以在运行时根据需要又选择的，俺顺序地使用装饰功能包装对象了。
             * 
             *  
             *  用自己的话说，
             *  现在你有一个乒乓球拍底板（B 主类），现在 B 只有一个最基本的功能，就是接球，发球。
             *  过了一段时间，你看到隔壁小张打的球很诡异，老是往你脸上窜，而且旋转强烈
             *  于是你也向打出旋转强烈的球，于是你用巨资买了两张国狂飙的胶皮（P），买了具有挥发性的胶水(S)
             *  由于手出汗，你又买了手胶（J）,球的弹性不够，体验不好,你又买了一盒三星球（Q）,衣服不透气，又买了一套乒乓球服（F）
             *  鞋子摩擦不够，老是打滑，然后你有买了乒乓球训练鞋（X）。
             *  本质上就是利用了 子类继承父类，子类拥有父类的属性和行为的特点。
             * 
             * 
             * 
             */

        }

        /// <summary>
        /// 主类
        /// </summary>
       public class B :Person
        {
       
            public B() { }
            protected Person component;

            public void Test(Person component)
            {
                this.component = component;
            }
            public virtual void show()
            {
                if (component != null)
                {
                    component.show();
                }
            }

        }
        /// <summary>
        /// 所需物品类
        /// </summary>
        class Goods :B
        {
            protected B b;

            public void Test(B _b)
            {
                this.b = _b;
            }

            public override void show()
            {
                if (this.b != null)
                {
                    b.show();
                }
            }
        }

        /// <summary>
        /// 胶皮
        /// </summary>
        class P : Goods
        {
            public override void show()
            {
                Console.WriteLine("胶皮");
                base.show();
            }
        }
        /// <summary>
        /// 胶水
        /// </summary>
        class S : Goods
        {
            public override void show()
            {
                Console.WriteLine("胶水");
                base.show();
            }
        }
        /// <summary>
        /// 手胶
        /// </summary>
        class J : Goods
        {
            public override void show()
            {
                Console.WriteLine("手胶");
                base.show();
            }
        }

        class Q : Goods
        {
            public override void show()
            {
                Console.WriteLine("三星球");
                base.show();
            }
        }
        /// <summary>
        /// 球服
        /// </summary>
        class F : Goods
        {
            public override void show()
            {
                Console.WriteLine("球服");
                base.show();
            }
        }

        class X : Goods
        {
            public override void show()
            {
                Console.WriteLine("球鞋");
                base.show();
            }
        }


    }
}
